/*
 * @Author: szx
 * @Date: 2022-03-09 16:23:47
 * @LastEditTime: 2022-03-09 17:24:50
 * @Description:
 * @FilePath: \MDN_JS学习\手撸JS源码\Promiseall.js
 */

/**
 * Promise全部执行完
 * @param {Array<Promise|Number>} iterable
 * @return {Promise}
 */
const PromiseAll = function (iterable) {
    // 如果是非迭代对象，直接返回
    const iterator = Symbol.iterator;
    if (!iterable[iterator]) return;
    const len = iterable.length;
    if (len == 0) return Promise.resolve(iterable);
    // 返回对象肯定是个Promise
    return new Promise((resolve, reject) => {
        // 结果数组
        let result = [];
        let cnt = 0;
        for (let [index, value] of iterable.entries()) {
            // 如果不是Promise对象，直接添加
            if (!(value instanceof Promise)) {
                value = Promise.resolve(value);
                /* 本来写成这样子的，但是发现Promise.all
                 * 传的不是promise数组，比如[1,2]，也不是同步返回
                 * 反而还是在pending，执行过程依然是异步的
                 * 所以需要套娃一个Promise，变成异步的
                result[index] = value;
                cnt++;
                if (cnt == len) resolve(result);
                */
            }
            value
                .then((res) => {
                    result[index] = res;
                    cnt++;
                    if (cnt == len) resolve(result);
                })
                .catch((err) => reject(err));
        }
    });
};

/* 例子1 */
// var p1 = Promise.resolve(3);
// var p2 = 1337;
// var p3 = new Promise((resolve, reject) => {
//     setTimeout(resolve, 100, 'foo');
// });
// 原版
// Promise.all([p1, p2, p3]).then((values) => {
//     console.log(values); // [3, 1337, "foo"]
// });
// // 自己版本
// PromiseAll([p1, p2, p3]).then((values) => {
//     console.log(values); // [3, 1337, "foo"]
// });

/* 例子2 */
// Promise.all([1, 2, 3]).then((value) => console.log(value));
// PromiseAll([1, 2, 3]).then((value) => console.log(value));

// Promise.all([1, 2, 3, Promise.resolve(444)]).then((value) => console.log(value));
// PromiseAll([1, 2, 3, Promise.resolve(444)]).then((value) => console.log(value));

// Promise.all([1, 2, 3, Promise.reject(555)])
//     .then((value) => console.log(value))
//     .catch((err) => console.log(err));
// PromiseAll([1, 2, 3, Promise.reject(555)])
//     .then((value) => console.log(value))
//     .catch((err) => console.log(err));

/* 例子3 */
// var p = Promise.all([]); // will be immediately resolved
// var p2 = Promise.all([1337, "hi"]); // non-promise values will be ignored, but the evaluation will be done asynchronously
// console.log(p);
// console.log(p2)
// setTimeout(function(){
//     console.log('the stack is now empty');
//     console.log(p2);
// });
// var p = PromiseAll([]); // will be immediately resolved
// var p2 = PromiseAll([1337, 'hi']); // non-promise values will be ignored, but the evaluation will be done asynchronously
// console.log(p);
// console.log(p2);
// setTimeout(function () {
//     console.log('the stack is now empty');
//     console.log(p2);
// });

var p1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 10000, 'foo');
});
var p2 = Promise.reject(555);
var p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
    .then((value) => console.log(value))
    .catch((err) => console.log(err));

// PromiseAll([p1, p2, p3])
//     .then((value) => console.log(value))
//     .catch((err) => console.log(err));
